<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <ul>
        <li><router-link to="/home">Home</router-link></li>
        <li><router-link to="/post/1">post1</router-link></li>
        <li><router-link to="/post/2">post2</router-link></li>
      </ul>
      <router-view></router-view>
    </div>
    <script src="vue.js"></script>
    <script src="vue-router.js"></script>
    <script>
      const  getPost  =  (id,callback)=>{
        setTimeout(()=>{
          callback(null,{
            id,
            title:`title_${id}`,
            content:`content_${id}`
          });
        },1000);
      }
      const Home = {
        template: `<div>Home</div>`,
      };
      const Post = {
        template:`
          <div>
            <div v-if="loading">
              loading......
            </div>
            <div v-if="error">
              {{error}}
            </div>
            <div v-if="post">
              <h2>{{post.title}}</h2>
              <p>{{post.content}}</p>
            </div>
          </div>
        `,
        data(){
          return {
            loading:false,//是否已经处于加载中了
            error:null,//表示请求后端接口数据的时候是否出错，如果出错了，出错的信息放在这
            post:null//从后端接口返回的文章对象 title content 
          }
        },
        beforeRouteEnter(to,from,next){
          //在进入路由前执行此守卫.调用API接口获取数据
          getPost(to.params.id,(error,post)=>{
            //把一个回调函数传递给next
            //好么导航会继续执行，并且在执行结束后，创建Vue组件实例后把新创建的Vue实例传递给回调函数
            next(vm=>vm.setData(error,post));
          });
        },
        //当从/post/1跳转到/post/2的时候，其实走的是路由组件的更新逻辑
        beforeRouteUpdate(to,from,next){
          //先把文章和error清空
          this.post = this.error = null;
          //尝试重新请求并获取数据
          getPost(to.params.id,(error,post)=>{
            //因为在更新的时候Vue实例已经存在，可以直接调用this.setData
            this.setData(error,post)
            //调用next进行确认导航 
            next();
          });
        },
        methods:{
          setData(error,post){
            if(error){
              this.error = error;
            }else{
              this.post = post;
            }
          },
          fetchData(){
            //先把错误对象和文章对象设置为null
            this.error = this.post  = null;
            //把加载中的标识设置为true
            this.loading = true;
            getPost(this.$route.params.id,(error,post)=>{
              //因为请求接口数据是异步的，需要通过回调函数接收返回值
              //如果请求过程中发生了错误
              if(error){
                //给error赋值
                this.error = error;
              }else{
                //把后端接口返回的post对象赋值给this.post
                this.post = post;
              }
              //再把loading设置为false,表示加载结束
              this.loading = false;
            });
          }
        }
      }

      const routes = [
        { 
          name: "home", 
          path: "/home", 
          component: Home 
        },
        { 
          name: "post", 
          path: "/post/:id", 
          component: Post 
        }
      ];

      var router = new VueRouter({
        routes,
      });
      
      var vm = new Vue({
        el: "#app",
        router,
        
      });
      // slide-left: 向左滑动; 5. slide-right: 向右滑动
    </script>
  </body>
</html>
